#include "Inf_W25Q32.h"

void Inf_W25Q32_Init(void)
{
    //Driver_SPI_Init();
}

void Inf_W25Q32_ReadID(uint8_t *mid, uint16_t *did)
{
    Driver_SPI_Start();
    /* 1. 发送 Jedec id指令 */
    Driver_SPI_SwapByte(0x9f);
    /* 2. 获取厂商id (发送的数据随意)*/
    *mid = Driver_SPI_SwapByte(0xff);

    /* 3. 获取设备id */
    *did = 0;
    *did |= Driver_SPI_SwapByte(0xff) << 8;
    *did |= Driver_SPI_SwapByte(0xff);

    Driver_SPI_Stop();
}
/// @brief 等待到存储器为空闲状态
void Inf_W25Q32_WaiteNbusy(void)
{
    Driver_SPI_Start();
    Driver_SPI_SwapByte(0x05);
    //busy=1代表忙碌 BUSY=0代表非忙碌
    while (Driver_SPI_SwapByte(0xff) & 0x01)
        ;
    Driver_SPI_Stop();
}

void Inf_W25Q32_WriteEnable(void)
{
    Driver_SPI_Start();
    Driver_SPI_SwapByte(0x06);
    Driver_SPI_Stop();
}

void Inf_W25q32_WriteDisenable(void)
{
    Driver_SPI_Start();
    Driver_SPI_SwapByte(0x04);
    Driver_SPI_Stop();
}

void Inf_W25Q32_EraseSector(uint8_t block, uint8_t sector)
{
    /* 擦除就是把内存数据全写1 */
    Inf_W25Q32_WaiteNbusy();
    Inf_W25Q32_WriteEnable();
    /* 计算出要擦除的扇区的首地址 */
    uint32_t sectorAddr = block * 0x010000 + sector * 0x001000; //?

    Driver_SPI_Start();
    Driver_SPI_SwapByte(0x20);
    Driver_SPI_SwapByte(sectorAddr >> 16 & 0xff); // 块
    Driver_SPI_SwapByte(sectorAddr >> 8 & 0xff);  // 区
    Driver_SPI_SwapByte(sectorAddr & 0xff);       // 页
    Driver_SPI_Stop();

    Inf_W25q32_WriteDisenable();
}

void Inf_W25Q32_WritePage(uint8_t block, uint8_t sector, uint8_t page, uint8_t *data, uint16_t len)
{
    Inf_W25Q32_EraseSector(block,sector);//先擦除目标扇区
    Inf_W25Q32_WaiteNbusy();
    Inf_W25Q32_WriteEnable();
    Driver_SPI_Start();
    /* 计算出要写入的数据的页的首地址 */
    uint32_t pageAddr = block * 0x010000 + sector * 0x001000 + page * 0x000100;

    Driver_SPI_Start();
    Driver_SPI_SwapByte(0x02);

    Driver_SPI_SwapByte(pageAddr >> 16 & 0xff);
    Driver_SPI_SwapByte(pageAddr >> 8 & 0xff);
    Driver_SPI_SwapByte(pageAddr & 0xff);

    for (uint16_t i = 0; i < len; i++)
    {
        Driver_SPI_SwapByte(data[i]);
    }
    Driver_SPI_Stop();
    Inf_W25q32_WriteDisenable();
}

void Inf_W25Q32_Read(uint8_t block, uint8_t sector, uint8_t page, uint8_t *data, uint16_t len)
{
    Inf_W25Q32_WaiteNbusy();

    uint32_t pageAddr = block * 0x010000 + sector * 0x001000 + page * 0x000100;

    Driver_SPI_Start();
    Driver_SPI_SwapByte(0x03);

    Driver_SPI_SwapByte(pageAddr >> 16 & 0xff);
    Driver_SPI_SwapByte(pageAddr >> 8 & 0xff);
    Driver_SPI_SwapByte(pageAddr & 0xff);
    for (uint16_t i = 0; i < len; i++)
    {
        data[i] = Driver_SPI_SwapByte(0xff);
    }

    Driver_SPI_Stop();
}
